package com.bigdata.movieticketapi.common.utils;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.xml.bind.DatatypeConverter;
import java.time.Duration;
import java.util.Date;
import java.util.Map;

@Component
@Slf4j
public class JwtUtil {
    @Value("${jwt.secret-key}")
    private String secretKey;
    @Value("${jwt.exp-time}")
    private Duration expTime;

    /**
     * 签发Token
     * @param subject:一般用来存用户ID
     * @param claims:存储再JWT的内容，一般不会存敏感信息
     * @return
     */
    public String createToken(String subject, Map<String,Object> claims){
        JwtBuilder builder = Jwts.builder();
        /**
         * 负载主要存一下放置再jwt的信息
         * 不建议存敏感信息
         */
        if(claims!=null){
            builder.setClaims(claims);
        }
        /**
         * 主题 一般存用户ID
         */
        if (StringUtils.hasLength(subject)){
            builder.setSubject(subject);
        }
        /**
         * 签发时间
         */
        long currentTimeMillis = System.currentTimeMillis();
        builder.setIssuedAt(new Date(currentTimeMillis));
        long millis = expTime.toMillis();
        /**
         * 过期时间
         */
        if(millis>0){
            long expMillis = currentTimeMillis + millis;
            builder.setExpiration(new Date(expMillis));
        }
        /**
         * 签名密钥 不要对外公布
         */
        if(StringUtils.hasLength(secretKey)){
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
            builder.signWith(signatureAlgorithm, DatatypeConverter.parseBase64Binary(secretKey));
        }
        return builder.compact();
    }

    /**
     * 解析token
     */
    public Claims pareToken(String token){
        try{
            return Jwts.parser().
                    setSigningKey(DatatypeConverter.parseBase64Binary(secretKey))
                    .parseClaimsJws(token).getBody();
        }catch (Exception ignored){
            log.error("pareToken:{}",ignored);
            return null;
        }
    }

    /**
     * 获取用户ID方法
     * @param token
     * @return
     */
    public String getUserId(String token){
        Claims claims = pareToken(token);
        if(claims!=null){
            return claims.getSubject();
        }
        return null;
    }

    /**
     * 校验token是否符合要求
     * true:校验通过
     * false:校验失败
     */
    public boolean validateToken(String token){
        try{
            Claims claims = pareToken(token);
            Date exp = claims.getExpiration();
            return exp.after(new Date());
        }catch (Exception ignored){
            log.error("validateToken:{}",ignored);
            return false;
        }

    }
}
